#include "material/terrainmatreial2.h"


CTerrainMaterial2::CTerrainMaterial2() :
CMaterial() {
    strcpy( m_strName, "TerrainMaterial2" );
}
CTerrainMaterial2::~CTerrainMaterial2() {

}
void CTerrainMaterial2::Init() {
    CMaterial::Init();

    const char* _strVertexShader = "\
/*#ifdef __HIGHTP__*/ \n\
    precision highp float; \n\
/*#endif*/ \n\
uniform mat4 projectionMatrix;\
uniform mat4 viewMatrix;\
uniform mat4 modelMatrix;\
uniform mat3 normalMatrix;\
uniform mat4 directionalShadowMatrix;\
varying vec4 vDirectionalShadowCoord[1];\
attribute vec3 a_position;\
attribute vec3 a_normal0; \
attribute vec2 a_texcoord0;\
attribute vec2 a_texcoord1;\
attribute vec2 a_texcoord2;\
attribute vec2 a_texcoord3;\
varying vec3 vNormal;\
varying vec2 vUv0;\
varying vec2 vUv1;\
varying vec2 vUv2;\
varying vec2 vUv3;\
varying float fogDepth;\n\
void main(){\
vNormal = normalize( normalMatrix * a_normal0);\
vec4 transformed = vec4( a_position, 1.0 );\
vec4 mvPosition = modelMatrix * transformed;\
vDirectionalShadowCoord[0] = directionalShadowMatrix * mvPosition;\
mvPosition = viewMatrix * mvPosition; \
fogDepth = -mvPosition.z; \
gl_Position = projectionMatrix * mvPosition;\
vUv0 = a_texcoord0;\
vUv1 = a_texcoord1;\
vUv2 = a_texcoord2;\
vUv3 = a_texcoord3;\
}";


    const char* _strFragmentShader =
        "                                \
/*#ifdef __HIGHTP__*/ \n\
    precision highp float; \n\
/*#endif*/ \n\
uniform vec4 lightEnable;\
uniform sampler2D diffuseMap[4]; \
uniform vec4 fogEnable;\n\
uniform vec4 fogColor; \
uniform vec4 fogInfo; \
varying vec3 vNormal;\
varying vec2 vUv0; \
varying vec2 vUv1; \
varying vec2 vUv2; \
varying vec2 vUv3; \
varying float fogDepth;\n\
struct DirectionalLight{\n\
    vec3 direction;\n\
    vec3 color;\n\
    vec4 shadow;\n\
    vec4 shadowInfo;\n\
};\n\
uniform DirectionalLight directionalLights[1];\n\
vec4 ads( vec3 LightColor, vec3 LightDir ){\n\
    vec3 _vLightColor = LightColor * dot(vNormal, LightDir); \n\
    return vec4( max(_vLightColor,LightColor * 0.285), 1.0 ); \n\
}\
const float PackUpscale = 256. / 255.; const float UnpackDownscale = 255. / 256.;\n\
const vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\n\
const vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\n\
float unpackRGBAToDepth( const in vec4 v ){\n\
    return dot( v, UnpackFactors );\n\
}\n\
uniform sampler2D directionalShadowMap[1]; \n\
varying vec4 vDirectionalShadowCoord[1]; \n\
float texture2DCompare( sampler2D depths, vec2 uv, float compare ){ \n\
    return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) ); \n\
} \n\
float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ){ \n\
    const vec2 offset = vec2( 0.0, 1.0 ); \n\
    vec2 texelSize = vec2( 1.0 ) / size; \n\
    vec2 centroidUV = floor( uv * size + 0.5 ) / size; \n\
    float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare ); \n\
    float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare ); \n\
    float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare ); \n\
    float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare ); \n\
    vec2 f = fract( uv * size + 0.5 ); \n\
    float a = mix( lb, lt, f.y ); \n\
    float b = mix( rb, rt, f.y ); \n\
    float c = mix( a, b, f.x ); \n\
    return c; \n\
} \n\
float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ){ \n\
    float shadow = 1.0; \n\
    shadowCoord.xyz /= shadowCoord.w; \n\
    shadowCoord.z += shadowBias; \n\
    bvec4 inFrustumVec = bvec4( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 ); \n\
    bool inFrustum = all( inFrustumVec ); \n\
    bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 ); \n\
    bool frustumTest = all( frustumTestVec ); \n\
    if( frustumTest ){ \n\
        vec2 texelSize = vec2( 1.0 ) / shadowMapSize; \n\
        float dx0 = - texelSize.x * shadowRadius; \n\
        float dy0 = - texelSize.y * shadowRadius; \n\
        float dx1 = + texelSize.x * shadowRadius; \n\
        float dy1 = + texelSize.y * shadowRadius; \n\
        shadow = ( \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) + \n\
            texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z ) \n\
            ) * (1.0 / 9.0); \n\
    } \n\
    return shadow; \n\
} \n\
void main() {\
    vec4 _color0 = texture2D(diffuseMap[0], vUv0); \
    vec4 _color1 = texture2D(diffuseMap[1], vUv1); \
    vec4 _color2 = texture2D(diffuseMap[2], vUv2); \
    vec4 _color3 = texture2D(diffuseMap[3], vUv3); \
    vec4 texelColor = _color0; \
    texelColor = mix(texelColor, _color1, _color1.a);\
    texelColor = mix(texelColor, _color2, _color2.a);\
    texelColor = mix(texelColor, _color3, _color3.a);\
    if( lightEnable.x == 0 ) \
        gl_FragColor = texelColor  * 1.0;\
    else{ \
        DirectionalLight directionalLight; \n\
        directionalLight = directionalLights[0]; \n\
        vec3 _lightcolor = ads( directionalLight.color, directionalLight.direction );\
        float _shadow = max( 0.45, getShadow( directionalShadowMap[0], vec2(directionalLight.shadowInfo.z, directionalLight.shadowInfo.w), directionalLight.shadowInfo.x, directionalLight.shadowInfo.y, vDirectionalShadowCoord[0] )); \n\
        gl_FragColor = (texelColor * (vec4(_lightcolor * _shadow, 1.0)) * 1.0 ); \
    } \n\
    if( fogEnable.x > 0 ){\n\
        float fogFactor = smoothstep( fogInfo.x, fogInfo.y, fogDepth ); \n\
        gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor.rgb, fogFactor ); \n\
    }\n\
}";
 
    m_hMaterialHandle = Material_Create(m_strName, (byte*)_strVertexShader, strlen(_strVertexShader), (byte*)_strFragmentShader, strlen(_strFragmentShader));
    m_hProjectionMatrixHandle = Material_GetUniform( m_hMaterialHandle, "projectionMatrix", EUT_MATRIX44 );
    m_hViewMatrixHandle = Material_GetUniform( m_hMaterialHandle, "viewMatrix", EUT_MATRIX44 );
    m_hModelMatrixHandle = Material_GetUniform( m_hMaterialHandle, "modelMatrix", EUT_MATRIX44 );
    m_hNormalMatrixHandle = Material_GetUniform( m_hMaterialHandle, "normalMatrix", EUT_MATRIX33 );
    m_hFogEnableHandle = Material_GetUniform( m_hMaterialHandle, "fogEnable", EUT_VEC4 );
    m_hFogColorHandle = Material_GetUniform( m_hMaterialHandle, "fogColor", EUT_VEC4 );
    m_hFogInfoHandle = Material_GetUniform( m_hMaterialHandle, "fogInfo", EUT_VEC4 );

    //m_hDiffuseHandle = Material_GetUniform( m_hMaterialHandle, "diffuse", EUT_VEC4 );

    m_hvDiffuseMapHandle[0] = Material_GetUniform( m_hMaterialHandle, "diffuseMap[0]", EUT_SAMPLER );
    m_hvDiffuseMapHandle[1] = Material_GetUniform( m_hMaterialHandle, "diffuseMap[1]", EUT_SAMPLER );
    m_hvDiffuseMapHandle[2] = Material_GetUniform( m_hMaterialHandle, "diffuseMap[2]", EUT_SAMPLER );
    m_hvDiffuseMapHandle[3] = Material_GetUniform( m_hMaterialHandle, "diffuseMap[3]", EUT_SAMPLER );

    m_hLightEnableHandle = Material_GetUniform( m_hMaterialHandle, "lightEnable", EUT_VEC4 );
    m_hDirectionalShadowMatrixHandle = Material_GetUniform( m_hMaterialHandle, "directionalShadowMatrix", EUT_MATRIX44 );
    m_hDirectionalShadowMap_0Handle = Material_GetUniform( m_hMaterialHandle, "directionalShadowMap[0]", EUT_SAMPLER );
    m_hDirectionalLights_0_colorHandle = Material_GetUniform( m_hMaterialHandle, "directionalLights[0].color", EUT_VEC3 );
    m_hDirectionalLights_0_directionHandle = Material_GetUniform( m_hMaterialHandle, "directionalLights[0].direction", EUT_VEC3 );
    m_hDirectionalLights_0_shadowHandle = Material_GetUniform( m_hMaterialHandle, "directionalLights[0].shadow", EUT_VEC4 );
    m_hDirectionalLights_0_shadowInfoHandle = Material_GetUniform( m_hMaterialHandle, "directionalLights[0].shadowInfo", EUT_VEC4 );

}

